/*
interface i_myinterface
{
    public function hello();
}
 
class parent_class implements i_myinterface
{
    public function hello()
    {
        echo "Good Morning!\n";
    }
}
 
final class myclass extends parent_class
{
    public function call_hello()
    {
        $this->hello();
    }
}
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_sample1.h"
#include "zend_interfaces.h"

/* If you declare any globals in php_sample1.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(sample1)
*/

//在定义一个类时往往会使其继承某个父类或者实现某个接口，在扩展中实现这个功能非常方便

/* True global resources - no need for thread safety here */
static int le_sample1;
zend_class_entry *i_myinterface_ce,*parent_class_ce,*myclass_ce;

//parent_class的hello方法
ZEND_METHOD(parent_class,hello)
{
    php_printf("hello world!\n");
}
 
//myclass的call_hello方法
ZEND_METHOD(myclass,call_hello)
{
    //这里涉及到如何调用对象的方法，详细内容下一章叙述
    zval *this_zval;
    this_zval = getThis();
    zend_call_method_with_0_params(&this_zval,myclass_ce,NULL,"hello",NULL);
}

//各自的zend_function_entry
static zend_function_entry i_myinterface_method[]={
    ZEND_ABSTRACT_ME(i_myinterface, hello,  NULL)
    {NULL,NULL,NULL}
};
 
static zend_function_entry parent_class_method[]={
    ZEND_ME(parent_class,hello,NULL,ZEND_ACC_PUBLIC)
    {NULL,NULL,NULL}
};
 
static zend_function_entry myclass_method[]={
    ZEND_ME(myclass,call_hello,NULL,ZEND_ACC_PUBLIC)
    {NULL,NULL,NULL}
};
/* {{{ PHP_INI
 */
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
    STD_PHP_INI_ENTRY("sample1.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_sample1_globals, sample1_globals)
    STD_PHP_INI_ENTRY("sample1.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_sample1_globals, sample1_globals)
PHP_INI_END()
*/
/* }}} */

/* Remove the following function when you have successfully modified config.m4
   so that your module can be compiled into PHP, it exists only for testing
   purposes. */

/* Every user-visible function in PHP should document itself in the source */
/* {{{ proto string confirm_sample1_compiled(string arg)
   Return a string to confirm that the module is compiled in */
PHP_FUNCTION(confirm_sample1_compiled)
{
	char *arg = NULL;
	size_t arg_len, len;
	char *strg;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) {
		return;
	}

	//strg = strpprintf(0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "sample1", arg);

	//RETURN_STR(strg);
	RETURN_STRING("Hello World", 1);
}
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and
   unfold functions in source code. See the corresponding marks just before
   function definition, where the functions purpose is also documented. Please
   follow this convention for the convenience of others editing your code.
*/


/* {{{ php_sample1_init_globals
 */
/* Uncomment this function if you have INI entries
static void php_sample1_init_globals(zend_sample1_globals *sample1_globals)
{
	sample1_globals->global_value = 0;
	sample1_globals->global_string = NULL;
}
*/
/* }}} */

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(sample1)
{
	/* If you have INI entries, uncomment these lines
	REGISTER_INI_ENTRIES();
	*/
	zend_class_entry ce,p_ce,i_ce;
    INIT_CLASS_ENTRY(i_ce,"i_myinterface",i_myinterface_method);
    i_myinterface_ce = zend_register_internal_interface(&i_ce TSRMLS_CC);
     
    //定义父类，最后使用zend_class_implements函数声明它实现的接口
    INIT_CLASS_ENTRY(p_ce,"parent_class",parent_class_method);
    parent_class_ce = zend_register_internal_class(&p_ce TSRMLS_CC);
    zend_class_implements(parent_class_ce TSRMLS_CC,1,i_myinterface_ce);
	
	//定义子类，使用zend_register_internal_class_ex函数
    INIT_CLASS_ENTRY(ce,"myclass",myclass_method);
    myclass_ce = zend_register_internal_class_ex(&ce,parent_class_ce,"parent_class" TSRMLS_CC);
    //注意：ZEND_ACC_FINAL是用来修饰方法的，而ZEND_ACC_FINAL_CLASS是用来修饰类的
    myclass_ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(sample1)
{
	/* uncomment this line if you have INI entries
	UNREGISTER_INI_ENTRIES();
	*/
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(sample1)
{
#if defined(COMPILE_DL_SAMPLE1) && defined(ZTS)
	ZEND_TSRMLS_CACHE_UPDATE();
#endif
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
 */
PHP_RSHUTDOWN_FUNCTION(sample1)
{
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(sample1)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "sample1 support", "enabled");
	php_info_print_table_end();

	/* Remove comments if you have entries in php.ini
	DISPLAY_INI_ENTRIES();
	*/
	
 
    
	return SUCCESS;
}
/* }}} */

/* {{{ sample1_functions[]
 *
 * Every user visible function must have an entry in sample1_functions[].
 */
const zend_function_entry sample1_functions[] = {
	PHP_FE(confirm_sample1_compiled,	NULL)		/* For testing, remove later. */
	PHP_FE_END	/* Must be the last line in sample1_functions[] */
};
/* }}} */

/* {{{ sample1_module_entry
 */
zend_module_entry sample1_module_entry = {
	STANDARD_MODULE_HEADER,
	"sample1",
	sample1_functions,
	PHP_MINIT(sample1),
	PHP_MSHUTDOWN(sample1),
	PHP_RINIT(sample1),		/* Replace with NULL if there's nothing to do at request start */
	PHP_RSHUTDOWN(sample1),	/* Replace with NULL if there's nothing to do at request end */
	PHP_MINFO(sample1),
	PHP_SAMPLE1_VERSION,
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_SAMPLE1
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
ZEND_GET_MODULE(sample1)
#endif

